package leju.common.widget;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.ViewConfiguration;
import android.widget.ZoomControls;

import com.leju.common.util.Logger;

public class ImageViewScaleTouch extends ImageViewScaleTouchBase
{

	static final float MIN_ZOOM = 0.7f;
	protected ScaleGestureDetector mScaleDetector;
	protected GestureDetector mGestureDetector;
	protected int mTouchSlop;
	protected float mCurrentScaleFactor;
	protected float mScaleFactor;
	protected int mDoubleTapDirection;
	protected OnGestureListener mGestureListener;
	protected OnScaleGestureListener mScaleListener;
	protected boolean mDoubleTapEnabled = true;
	protected boolean mScaleEnabled = true;
	protected boolean mScrollEnabled = true;
	private ZoomControls zc;
	private int position = -1;

	public ImageViewScaleTouch(Context context, AttributeSet attrs)
	{
		super(context, attrs);
	}
	public ImageViewScaleTouch(Context context)
	{
		this(context, null);
	}

	@Override
	protected void init()
	{
		super.init();
		mTouchSlop = ViewConfiguration.getTouchSlop();
		mGestureListener = getGestureListener();
		mScaleListener = getScaleListener();

		mScaleDetector = new ScaleGestureDetector(getContext(), mScaleListener);
		mGestureDetector = new GestureDetector(getContext(), mGestureListener,
				null, true);

		mCurrentScaleFactor = 1f;
		mDoubleTapDirection = 1;
	}

	public void setDoubleTapEnabled(boolean value)
	{
		mDoubleTapEnabled = value;
	}

	public void setScaleEnabled(boolean value)
	{
		mScaleEnabled = value;
	}

	public void setScrollEnabled(boolean value)
	{
		mScrollEnabled = value;
	}

	public boolean getDoubleTapEnabled()
	{
		return mDoubleTapEnabled;
	}

	protected OnGestureListener getGestureListener()
	{
		return new GestureListener();
	}

	protected OnScaleGestureListener getScaleListener()
	{
		return new ScaleListener();
	}

	@Override
	protected void onBitmapChanged(Drawable drawable)
	{
		super.onBitmapChanged(drawable);

		float v[] = new float[9];
		mSuppMatrix.getValues(v);
		mCurrentScaleFactor = v[Matrix.MSCALE_X];
	}

	@Override
	protected void _setImageDrawable(final Drawable drawable,
			final boolean reset, final Matrix initial_matrix,
			final float maxZoom)
	{
		super._setImageDrawable(drawable, reset, initial_matrix, maxZoom);
		mScaleFactor = getMaxZoom() / 3;
	}
	
	public float getTargetScale(float scale,boolean b)
	{
		if(b)//放大
		{			
			if ((scale + 1) <= getMaxZoom())
			{
				return scale +0.5f;
			} else
			{
				return getMaxZoom();
			}
		}else//缩小
		{
			if (scale  > 1f)
			{
				return scale - 0.5f;
			} else
			{
				return 1f;
			}
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		mScaleDetector.onTouchEvent(event);
		if (!mScaleDetector.isInProgress())
			mGestureDetector.onTouchEvent(event);

		int action = event.getAction();
		switch (action & MotionEvent.ACTION_MASK)
		{
		case MotionEvent.ACTION_UP:
			if (getScale() < 1f)
			{
				zoomTo(1f, 50);
			}
			break;
			
		}
		return true;
	}

	@Override
	protected void onZoom(float scale)
	{
		super.onZoom(scale);
		
		if (!mScaleDetector.isInProgress())
			mCurrentScaleFactor = scale;
	}

	protected float onDoubleTapPost(float scale, float maxZoom)
	{
		if (mDoubleTapDirection == 1)
		{
			if ((scale + (mScaleFactor * 2)) <= maxZoom)
			{
				return scale + mScaleFactor;
			} else
			{
				mDoubleTapDirection = -1;
				return maxZoom;
			}
		} else
		{
			mDoubleTapDirection = 1;
			return 1f;
		}
	}

	public class GestureListener extends
			GestureDetector.SimpleOnGestureListener
	{

		@Override
		public boolean onDoubleTap(MotionEvent e)
		{
			Logger.d("onDoubleTap");
			if (mDoubleTapEnabled)
			{
				float scale = getScale();
				float targetScale = scale;
				/*targetScale = onDoubleTapPost(scale, getMaxZoom());
				targetScale = Math.min(getMaxZoom(),
						Math.max(targetScale, MIN_ZOOM));*/
				if (targetScale < getMaxZoom()) {
					targetScale = getMaxZoom();
				} else {
					targetScale = 1.0f;//还原到开始大小
				}
				mCurrentScaleFactor = targetScale;
				zoomTo(targetScale, e.getX(), e.getY(), 200);
				invalidate();
			}
			return super.onDoubleTap(e);
		}

		@Override
		public void onLongPress(MotionEvent e)
		{
			if (isLongClickable())
			{
				if (!mScaleDetector.isInProgress())
				{
					setPressed(true);
					performLongClick();
				}
			}
		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY)
		{
			Logger.d("onScroll");
			if (!mScrollEnabled)
				return false;

			if (e1 == null || e2 == null)
				return false;
			if (e1.getPointerCount() > 1 || e2.getPointerCount() > 1)
				return false;
			if (mScaleDetector.isInProgress())
				return false;
			if (getScale() == 1f)
				return false;
			scrollBy(-distanceX, -distanceY);
			invalidate();
			return super.onScroll(e1, e2, distanceX, distanceY);
		}
		@Override
		public boolean onDown(MotionEvent e)
		{
			Logger.d("onDown");
			return super.onDown(e);
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY)
		{

			Logger.d("onFling");
			if (!mScrollEnabled)
				return false;

			if (e1.getPointerCount() > 1 || e2.getPointerCount() > 1)
				return false;
			if (mScaleDetector.isInProgress())
				return false;

			float diffX = e2.getX() - e1.getX();

			return super.onFling(e1, e2, velocityX, velocityY);

		}
	}

	public class ScaleListener extends
			ScaleGestureDetector.SimpleOnScaleGestureListener
	{

		@SuppressWarnings("unused")
		@Override
		public boolean onScale(ScaleGestureDetector detector)
		{
			Logger.d("onScale");
			float span = detector.getCurrentSpan() - detector.getPreviousSpan();
			float targetScale = mCurrentScaleFactor * detector.getScaleFactor();
			if (mScaleEnabled)
			{
				targetScale = Math.min(getMaxZoom(),
						Math.max(targetScale, MIN_ZOOM));
				zoomTo(targetScale, detector.getFocusX(), detector.getFocusY());
				mCurrentScaleFactor = Math.min(getMaxZoom(),
						Math.max(targetScale, MIN_ZOOM));
				mDoubleTapDirection = 1;
				invalidate();
				return true;
			}
			return false;
		}
	}
}
